/******************************************************************************/
package jamie.org.sil.www.usxUtils;


/******************************************************************************/
/**
 * A class to hold a single Bible reference.
 * <p>
 * 
 * Note that we assume book names are <i>supplied</i> to the present class in
 * vernacular form (full or abbreviated) and that numerals are also in
 * vernacular form.  You have a choice of how the output is supplied.
 * <p>
 * 
 * Note also that when outputting data, you can specify the length to be used
 * (full, abbreviated, or whatever the translator supplied).  This makes sense
 * only where you have requested vernacular output, because only for the
 * vernacular are we actually concerned with what the translator supplied.
 * For English output, the class is set up to return the abbreviated names.
 *
 * @author ARA "Jamie" Jamieson
**/

public class ParsedTextElementBibleRef extends ParsedTextElement
{
  /****************************************************************************/
  /****************************************************************************/
  /**                                                                        **/
  /**                                 Public                                 **/
  /**                                                                        **/
  /****************************************************************************/
  /****************************************************************************/

  /****************************************************************************/
  public ParsedTextElementBibleRef (String vernacularBookName, boolean bookNameDefaulted,
                                    String chapter, boolean chapterDefaulted,
                                    String chapterAndVerseSeparator, int chapterAndVerseSeparatorType,
                                    String verse, boolean verseDefaulted,
                                    String subverse)
  {
    /**************************************************************************/
    m_VernacularBookName = vernacularBookName;
    m_FullEnglishBookName = BibleDetails.instance().getFullUbsName_V(m_VernacularBookName);
    m_BookNameDefaulted = bookNameDefaulted;
    m_Chapter = chapter;
    m_ChapterDefaulted = chapterDefaulted;
    m_ChapterAndVerseSeparator = chapterAndVerseSeparator;
    m_ChapterAndVerseSeparatorType = chapterAndVerseSeparatorType;
    m_Verse = verse;
    m_VerseDefaulted = verseDefaulted;
    m_Subverse = subverse;
    m_UbsBookNo = BibleDetails.instance().getUbsBookNumber_E(m_FullEnglishBookName);
    m_SwapChapterAndVerse = "vc".equalsIgnoreCase(Config.instance().getChapterAndVerseDisplayOrder());
    

    
    /**************************************************************************/
    /* Deal with single chapter books like Jude.  It's _possible_ we may have
     * been given both chapter and verse, in which case I assume that's the
     * way we want to handle things.  Otherwise we'll have been given only
     * one number, which we'll have treated as the chapter (with the verse
     * being defaulted), but which should actually be the verse.
     */
    
    m_BookWithSingleChapterWasGivenVerseRefOnly = (m_VerseDefaulted && 1 == BibleDetails.instance().getChapterCount_E(m_FullEnglishBookName));
    if (m_BookWithSingleChapterWasGivenVerseRefOnly)
    {
      m_Verse = m_Chapter;
      m_VerseDefaulted = false;
      m_Chapter = NumeralProcessor.instance().toVernacular(1);
    }
  }

  
  /****************************************************************************/
  public boolean getBookNameDefaulted () { return m_BookNameDefaulted; }
  public String getChapter () { return m_Chapter; }
  public String getChapterAndVerseSeparator () { return m_ChapterAndVerseSeparator; }
  public int getChapterAndVerseSeparatorType () { return m_ChapterAndVerseSeparatorType; }
  public int getChapterAsInteger (NumeralProcessor numProc) { return numProc.fromVernacular(m_Chapter); }
  public boolean getChapterDefaulted () { return m_ChapterDefaulted; }
  public boolean getFormsPartOfRangeForWhichTargetDoesNotExist () { return m_FormsPartOfRangeForWhichTargetDoesNotExist; }
  public String getFullEnglishBookName () { return m_FullEnglishBookName; }
  @Override public int getNextSeparatorCode () { return m_NextSeparatorCode; }
  @Override public int getPreviousSeparatorCode () { return m_PreviousSeparatorCode; }
  @Override public String getSubverse () { return m_Subverse; }
  public String getVernacularBookName () { return m_VernacularBookName; }
  public String getVerse () { return m_Verse; }
  public int getVerseAsInteger (NumeralProcessor numProc) { return numProc.fromVernacular(m_Verse); }
  public boolean getVerseDefaulted () { return m_VerseDefaulted; }
  public void setFormsPartOfRangeForWhichTargetDoesNotExist (boolean val) { m_FormsPartOfRangeForWhichTargetDoesNotExist = val; }
  @Override public void setNextSeparatorCode (int val) { m_NextSeparatorCode = val; }
  @Override public void setPreviousSeparatorCode (int val) { m_PreviousSeparatorCode = val; }
  @Override public void setSubverse (String val) { m_Subverse = val; }
  @Override public String toString () { return ""; }
  
  
  
  /****************************************************************************/
  /**
   * Converts the reference to a string.
   * 
   * @return String representation.
   */
  
  @Override public String toString (BibleReferenceSupport.Length fullOrAbbreviated,
                                    BibleReferenceSupport.Language englishOrVernacular,
                                    int sepType,
                                    boolean includeDefaultedValues)
  {
    /**************************************************************************/
    String chapter = getChapter();
    boolean doIt = false;
    boolean haveOutputChapter = false;
    String res = "";
    String verse = getVerse();
    
    
    
    /**************************************************************************/
    if (m_SwapChapterAndVerse)
    {
      chapter = getVerse();
      verse = getChapter();
    }
    
    
    /**************************************************************************/
    if (!getBookNameDefaulted() || includeDefaultedValues)
    {
      if (BibleReferenceSupport.Language.C_Vernacular == englishOrVernacular &&
          BibleReferenceSupport.Length.C_AsSupplied == fullOrAbbreviated)
        res += m_VernacularBookName;
      else
      {
        if (BibleReferenceSupport.Length.C_AsSupplied == fullOrAbbreviated)
          fullOrAbbreviated = BibleReferenceSupport.Length.C_Abbreviated;
        res = BibleDetails.instance().getBookName(m_UbsBookNo, englishOrVernacular, fullOrAbbreviated);
      }
    }
 
    
    
    /**************************************************************************/
    doIt = includeDefaultedValues || !getChapterDefaulted();
    doIt = doIt && !m_BookWithSingleChapterWasGivenVerseRefOnly;
    if (doIt)
    {
      if (0 != res.length()) res += " ";
      String s = (englishOrVernacular == BibleReferenceSupport.Language.C_Vernacular ?
                    chapter :
                    Integer.toString(NumeralProcessor.instance().fromVernacular(chapter)));
      res += s;
      haveOutputChapter = true;
    }

    
    
    /**************************************************************************/
    doIt = haveOutputChapter && (includeDefaultedValues || !getVerseDefaulted());
    doIt = doIt && !m_BookWithSingleChapterWasGivenVerseRefOnly;
    if (doIt)
      res += (sepType == BibleReferenceSupport.C_SeparatorExternal ?
              BibleReferenceSupport.instance().getExternalChapterAndVerseSeparator() :
              BibleReferenceSupport.instance().getInternalChapterAndVerseSeparator());
    

    
    /**************************************************************************/
    doIt = includeDefaultedValues || !getVerseDefaulted();
    if (doIt)
    {
      String s = (englishOrVernacular == BibleReferenceSupport.Language.C_Vernacular ?
                    verse :
                    Integer.toString(NumeralProcessor.instance().fromVernacular(verse)));
      res += s + getSubverse();
    }
    
    return res;
  }


  /****************************************************************************/
  /**
   * Validates the reference.
   * 
   * @return String containing error details, or empty string if the reference
   *         is ok.
   */

  public String validate ()
  {
    NumeralProcessor proc = NumeralProcessor.instance();
    int chapter = proc.fromVernacular(m_Chapter);
    int verse = proc.fromVernacular(m_Verse);
    return BibleDetails.instance().isValidReference_E(m_FullEnglishBookName, chapter, 0 == verse ? 1 : verse);
  }

  
  
  
  
  /****************************************************************************/
  /****************************************************************************/
  /**                                                                        **/
  /**                                 Public                                 **/
  /**                                                                        **/
  /****************************************************************************/
  /****************************************************************************/

  private boolean m_BookNameDefaulted = false;
  private boolean m_BookWithSingleChapterWasGivenVerseRefOnly = false;
  private String m_Chapter = null;
  private String m_ChapterAndVerseSeparator = null;
  private int m_ChapterAndVerseSeparatorType = -1;
  private boolean m_ChapterDefaulted = false;
  private boolean m_FormsPartOfRangeForWhichTargetDoesNotExist = false;
  private String m_FullEnglishBookName = null;
  private int m_NextSeparatorCode = -1;
  private int m_PreviousSeparatorCode = -1;
  private String m_Subverse = null;
  private boolean m_SwapChapterAndVerse = false;
  private int m_UbsBookNo = 0;
  private String m_VernacularBookName = null;
  private String m_Verse = null;
  private boolean m_VerseDefaulted = false;
}
